home *** CD-ROM | disk | FTP | other *** search
/ Best of Shareware / Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso / mac / ZIPPED / DOS / GRAPHICS / R386DEV4.ZIP / SEGA / TIMER.C < prev   
C/C++ Source or Header  |  1992-09-17  |  6KB  |  239 lines

  1. /* Timer routines for REND386; written by Dave Stampe, July 1992 */
  2.  
  3. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  4.    May be freely used to write software for release into the public domain;
  5.    all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  6.    for permission to incorporate any part of this software into their
  7.    products!
  8.  */
  9.  
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <stdio.h>
  13. #include <conio.h>
  14. #include <stdlib.h>
  15. #include <signal.h>
  16.  
  17. /******************* TIMER INTERRUPT STUFF ****************/
  18.  
  19. #define TIMER_VECT 8        /* timer chip int. vector */
  20. #define UNUSED_VECT 128         /* user vector: used to link to std ISR */
  21.  
  22. #define PIC_CMD 0x20            /* constants for PIC EOI command */
  23. #define NONSPEC_EOI 0x20
  24. #define TIMER_MODE 0x34         /* timer setup command */
  25. #define TIMER_CONTROL 0x43    /* timer control register port */
  26. #define TIMER_0 0x40        /* timer 0 port */
  27.  
  28. #define LATCH_COUNT 0x00    /* command to latch count */
  29.  
  30. #define SYNC_INTERVAL 5          /* how many frames between resynchronization */
  31.  
  32. static void init_SG_timer(int time);
  33. static void reset_SG_timer();
  34.  
  35. static void interrupt fast_SG_timer();
  36. static void interrupt (*oldint)() = NULL; /* old timer ISR vector */
  37.  
  38. static unsigned int clock_rate = 0; /* calibrated timer rate for vertical */
  39. static unsigned int clock_rate_hi = 0;
  40. static unsigned int clock_rate_lo = 0;
  41.  
  42. static unsigned int divisor = 0; /* counter to emulate 18.2 Hz tick */
  43.  
  44. static int syncount = SYNC_INTERVAL; /* resync counter */
  45.  
  46. static long int_timer = 0; /* incremented each frame (use for timing) */
  47.  
  48. static void (*frame_interrupt_routine)() = NULL;
  49. static void (*glove_interrupt_routine)() = NULL;
  50.  
  51. static int glovecount = 0;
  52. static int glove_rate = 2; /* count of how many glove calls per frame */
  53.  
  54. /******************* FIND VERTICAL FRAME RATE *************/
  55.  
  56. #define ADVANCE 100             /* time (microseconds) of advance   */
  57.                                 /* in vert. interrupt.  Will act as */
  58.  
  59. static int find_sega_speed()  /* "vertical hold" adjustment       */
  60. {
  61.     unsigned int old, new; /* Routine to compute vertical frame    */
  62.  
  63.     vsync();
  64.     outportb(TIMER_CONTROL, TIMER_MODE);
  65.     outportb(TIMER_0, 0);
  66.     outportb(TIMER_0, 0); /* timer must count modulo 65536 */
  67.  
  68.     disable(); /* time of vert. retrace */
  69.     vsync();
  70.     outportb(TIMER_CONTROL,LATCH_COUNT);
  71.     enable();
  72.     old = inportb(TIMER_0) & 0xFF;
  73.     old |= (inportb(TIMER_0) << 8);
  74.  
  75.     vsync(); /* time 2 vert. retraces later */
  76.     disable();
  77.     vsync();
  78.     outportb(TIMER_CONTROL,LATCH_COUNT);
  79.     enable();
  80.     new = inportb(TIMER_0) & 0xFF;
  81.     new |= (inportb(TIMER_0) << 8);
  82.  
  83.     return ((old-new)>>1) - ADVANCE; /* compute interrupt rate */
  84. }
  85.  
  86.  
  87. long current_time()
  88. {
  89.     long i;
  90.  
  91.     disable();
  92.     i = int_timer;
  93.     enable();
  94.     return i;
  95. }
  96.  
  97. void set_current_time(long i)
  98. {
  99.     disable();
  100.     int_timer = i;
  101.     enable();
  102. }
  103.  
  104.  
  105. volatile int interrupts_occurred = 0;
  106.  
  107. static void interrupt fast_SG_timer() /* NEW TIMER ISR */
  108. {
  109.     unsigned int olddiv = divisor;
  110.  
  111.     disable();
  112.  
  113.     int_timer++;
  114.     interrupts_occurred++;
  115.  
  116.     if (frame_interrupt_routine == NULL) goto glove;
  117.     else frame_interrupt_routine(glovecount-1);
  118.     if (--glovecount <= 0) glovecount = glove_rate;
  119.     else goto glove;
  120.  
  121.  
  122.     syncount--;
  123.     if (syncount < 0)
  124.     {
  125.         syncount = SYNC_INTERVAL;
  126.         outportb(TIMER_CONTROL, TIMER_MODE); /* stop timer */
  127.         outportb(TIMER_0, 255);
  128.         outportb(TIMER_0, 255);
  129.         enable();
  130.         disable();
  131.         vsync();
  132.         outportb(TIMER_CONTROL, TIMER_MODE); /* restart timer */
  133.         outportb(TIMER_0, clock_rate_lo);
  134.         outportb(TIMER_0, clock_rate_hi);
  135.     }
  136.  
  137.  
  138. glove:
  139.  
  140.     if (glove_interrupt_routine) glove_interrupt_routine();
  141.     divisor += clock_rate; /* dec divide count */
  142.     if (divisor < olddiv) /* simulate 18.2 Hz ISR if time */
  143.         geninterrupt(UNUSED_VECT);
  144.  
  145.     outportb(PIC_CMD, NONSPEC_EOI);
  146.     enable();
  147. }
  148.  
  149.  
  150. static int ticks_per_second = 0;
  151.  
  152. int get_ticks_per_second()
  153. {
  154.     return ticks_per_second;
  155. }
  156.  
  157. static void reset_SG_timer();
  158.  
  159. static void init_SG_timer(int speed) /* SET UP FAST TIMER */
  160. {
  161.     atexit(reset_SG_timer); /* set traps for error, ctrl c, */
  162.     signal(SIGABRT, reset_SG_timer);
  163.     signal(SIGFPE, reset_SG_timer);
  164.     signal(SIGINT, reset_SG_timer);
  165.  
  166.     clock_rate = speed; /* save speed for future work */
  167.     ticks_per_second = 1190000L/speed;
  168.     clock_rate_hi = clock_rate >> 8;
  169.     clock_rate_lo = clock_rate & 255;
  170.  
  171.     divisor = 0; /* set up timers */
  172.     syncount = SYNC_INTERVAL;
  173.     int_timer = 0;
  174.  
  175.     if (getvect(UNUSED_VECT) == NULL)
  176.     { /* setup int's if required(first run) */
  177.         disable();
  178.         oldint = getvect(TIMER_VECT); /* setup ISR vectors */
  179.         setvect(UNUSED_VECT,oldint);
  180.         setvect(TIMER_VECT, fast_SG_timer);
  181.         outportb(TIMER_CONTROL, TIMER_MODE); /* load timer */
  182.         outportb(TIMER_0, clock_rate_lo);
  183.         outportb(TIMER_0, clock_rate_hi);
  184.         enable();
  185.     }
  186. }
  187.  
  188.  
  189. static void reset_SG_timer()   /* RESET PC TO NORMAL */
  190. {
  191.     disable();
  192.     setvect(TIMER_VECT, oldint); /* reset vector */
  193.     outportb(TIMER_CONTROL, TIMER_MODE); /* reset timer */
  194.     outportb(TIMER_0, 0);
  195.     outportb(TIMER_0, 0);
  196.     setvect(UNUSED_VECT,NULL); /* disconnect flag */
  197.     enable();
  198.  
  199.     signal(SIGINT, SIG_DFL);
  200.     signal(SIGABRT, SIG_DFL);
  201.     signal(SIGFPE, SIG_DFL);
  202. }
  203.  
  204. /* SET EVERYTHING UP         */
  205. /* (init. glove, Sega first) */
  206.  
  207. void init_SG_interrupt( void (*sega_switcher)(), /* NULL if no sega/video   */
  208.     void (*glove_handler)(),                     /* NULL if no glove driver */
  209.     int glove_tc)                                /* 1.19*uS (test interval) */
  210. {                                                /* 6500 sugg. ALWAYS (fast timer)  */
  211.     int i_rate;
  212.  
  213.     glove_interrupt_routine = glove_handler;
  214.     frame_interrupt_routine = sega_switcher;
  215.  
  216.     if (sega_switcher == NULL)
  217.         i_rate = glove_tc; /* glove only: use suggested speed */
  218.     else
  219.         {
  220.         i_rate = find_sega_speed(); /* use a multiple of video rate   */
  221.         if (glove_tc != 0)
  222.         {
  223.             glove_rate = i_rate/glove_tc; /* about 2x for 72 fps, 3x for 60 */
  224.  
  225.             if (glove_rate < 1) glove_rate = 1; /* handle no glove driver   */
  226.             if (glove_rate > 20) glove_rate = 20; /* come on now...           */
  227.             i_rate /= glove_rate;
  228.         }
  229.         else i_rate /=3;
  230.     }
  231.     init_SG_timer(i_rate); /* start 'er up! */
  232. }
  233.  
  234. void init_timer()
  235. {
  236.     init_SG_interrupt(NULL,NULL,6500);
  237. }
  238.  
  239.